/*
 * Disco.c
 *
 *  Created on: 10/10/2011
 *      Author: MadeyMaga
 */

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include "Planificador.h"
#include "Disco.h"

char 			*map;
int 			sz, paginas;
off_t 			size;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

extern int 		retardo;

int mapDisk()
{
	div_t 		division;
	struct stat st;
	int 		disk;

	disk = open(FILEPATH, O_RDWR);

	if(disk == -1)
	{
		printf("Error al abrir el disco. Error n°: %d, descripcion: %s.\n", errno, strerror(errno));
		return 1;
	}

	if(stat(FILEPATH, &st) != 0)
	{
		printf("Error en el Stat. Error n°: %d, descripcion: %s.\n", errno, strerror(errno));
		return 1;
	}

	size = st.st_size;

	sz = getpagesize();

	if(sz == 0)
	{
		return 1;
	}

	division = div(size, sz);

	if(division.rem != 0)
	{
		paginas = division.quot++;

	}else{

		paginas = division.quot;
	}

	map = mmap(NULL, paginas * sz, PROT_READ | PROT_WRITE,MAP_PRIVATE, disk, 0);

	posix_madvise(map, size, POSIX_MADV_SEQUENTIAL);

	printf("Mapeo ok.\n");

	if(map == (void *) -1)
	{
		printf("Error al realizar el map. Error n°: %d, descripcion: %s.\n", errno, strerror(errno));
		return 1;
	}

	return 0;
}

int leerSector(int sec, char **buffer)
{
	int 	num_byte;

	pthread_mutex_lock(&mutex);

	memset(*buffer, '0', 512);

	num_byte = sec * 512;

	if(sz < num_byte)
	{
		printf("Se solicito un sector que no forma parte del disco.\n");
		return 1;
	}

	memcpy(*buffer, &map[num_byte], 512);

	printf("%s\n", *buffer);

	pthread_mutex_unlock(&mutex);

	return 0;
}

int escribirSector(int sec, char **buffer)
{
	int 	num_byte, pagina, indice, syncRetVal;
	div_t 	division;

	num_byte = sec * 512;

	if(sz < num_byte)
	{
		printf("Se solicito un sector que no forma parte del disco.\n");
		return 1;
	}

	division = div(num_byte, sz);

	if (division.rem != 0)
	{
		pagina = division.quot++;

	} else {

		pagina = division.quot;
	}

	pthread_mutex_lock(&mutex);

	memcpy(buffer, &map[num_byte], 512);

	indice = pagina * sz;

	sleep(retardo);

	syncRetVal = msync(&map[indice], sz, MS_SYNC);

	pthread_mutex_unlock(&mutex);

	if(syncRetVal == -1)
	{
		printf("Error al realizar el msync. Error n°: %d, descripcion: %s.\n", errno, strerror(errno));
		return 2;
	}

	return 0;
}

void desmapear(void){

	 munmap(map, paginas * size);
}
